/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package server;

import comum.Message;
import java.util.Vector;
import server.entidades.User;
import java.net.Socket;
import java.util.Observable;
import java.util.Observer;
import server.colecoes.ColecaoCanal;
import server.colecoes.ColecaoUsuario;
import server.entidades.Channel;

/**
 *
 * @author root
 */
public class Server implements Runnable, Observer {

    private int portaEscuta = 7777;
    private boolean run;
    private ServerListener listener;
    private ColecaoUsuario usuarios = new ColecaoUsuario();
    private ColecaoCanal canais = new ColecaoCanal();
    private String servername = "sharptail";
    private String localhost = "localhost";

    public Server() {
        init();
        start();
    }

    public Server(int portaEscuta) {
        this.portaEscuta = portaEscuta;
        init();
        start();
    }

    private synchronized void init() {
        listener = new ServerListener(portaEscuta);
        listener.addObserver(this);
    }

    private synchronized void start() {
        Thread t = new Thread(this);
        t.start();
    }

    public void run() {
        Thread t = new Thread(listener);
        t.start();
        run = true;
        while (run) {
            Vector<User> usrs = new Vector<User>(usuarios.getUsuarios());
            for (User u : usrs) {
                if (u.getNickname() != null) {
                    u.transmitirMensagem(new Message("PING :" + u.getNickname() + "-lag"));
                }
                if(!u.isConectado()){
                    finalizarUsuario(u);
                }
            }
            try {
                Thread.sleep(10000);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    public synchronized void stop() {
        run = false;
        listener.stop();
        usuarios.stopAll();
        canais.stopAll();
    }

    public synchronized void update(Observable o, Object arg) { //cria evento e manda tratar
        if (o instanceof ServerListener) {
            if (arg instanceof Socket) {
                Socket soc = (Socket) arg;
                newUsuario(soc);
            }
        }
    }

    private synchronized void newUsuario(Socket s) {
        User user = new User(this, s);
        user.addObserver(this);
        usuarios.adicionarUsuario(user);
        new Thread(user).start();
    }

    public synchronized String getServerHost() {
        return servername + "@" + localhost;
    }

    public synchronized ColecaoUsuario getUsuarios() {
        return this.usuarios;
    }

    public synchronized String getName() {
        return this.servername;
    }

    public ColecaoCanal getCanais() {
        return this.canais;
    }

    public void removeUser(User u) {
        canais.rmUserFromAll(u);
        this.usuarios.removerUsuario(u);
    }

    public void finalizarUsuario(User usuario) {
        if (usuario.isConectado()) {
            System.out.println(">> " + usuario.getNickname() + " desconectou");
            removeUser(usuario);
            usuario.stop();
        }
    }
}
